package prh25.biblioteca.entity.dao.hibernate;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.AnnotationConfiguration;

/**
 * 
 *
 * @author Wilson
 */
public final class HibernateUtil {

	private static SessionFactory sessionFactory;

	private static final ThreadLocal threadSession = new ThreadLocal();

	private static final ThreadLocal threadTransaction = new ThreadLocal();

	static {
		try {
			sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
		} catch (Throwable ex) {
            ex.printStackTrace();
			throw new ExceptionInInitializerError(ex);
		}
	}

	private HibernateUtil() {

	}

	/**
	 * Returns the SessionFactory used for this static class.
	 * 
	 * @return SessionFactory
	 */
	public static SessionFactory getSessionFactory() {
		return sessionFactory;
	}

	/**
	 * Retrieves the current Session local to the thread. <p/> If no Session is
	 * open, opens a new Session for the running thread.
	 * 
	 * @return Session
	 */
	@SuppressWarnings("unchecked")
	public static Session getSession() {
		Session s = (Session) threadSession.get();

		if (s == null) {

			s = getSessionFactory().openSession();
			System.out.println("Abrindo uma sessao  . .. . . . " + s.toString());

			threadSession.set(s);
			beginTransaction();
		}

		return s;
	}

	/**
	 * Closes the Session local to the thread.
	 */
	@SuppressWarnings("unchecked")
	public static void closeSession() {

		Session s = (Session) threadSession.get();
		threadSession.set(null);
		if (s != null && s.isOpen()) {
			
			System.out.println("Fechando uma sessao  . .. . . . " + s.toString());
			s.close();
			
		}

	}

	/**
	 * Start a new database transaction.
	 */
	@SuppressWarnings("unchecked")
	public static void beginTransaction() {
		Transaction tx = (Transaction) threadTransaction.get();

		if (tx == null) {

			tx = getSession().beginTransaction();
			threadTransaction.set(tx);
		}

	}

	/**
	 * Commit the database transaction.
	 */
	@SuppressWarnings("unchecked")
	public static void commitTransaction() {
		Transaction tx = (Transaction) threadTransaction.get();

		if (tx != null && !tx.wasCommitted() && !tx.wasRolledBack()) {

			tx.commit();
		}
		threadTransaction.set(null);

	}

	/**
	 * Rollback the database transaction.
	 */
	@SuppressWarnings("unchecked")
	public static void rollbackTransaction() {
		Transaction tx = (Transaction) threadTransaction.get();
		try {
			threadTransaction.set(null);
			if (tx != null && !tx.wasCommitted() && !tx.wasRolledBack()) {

				tx.rollback();
			}

		} finally {
			closeSession();
		}
	}
}
